//--- Projeto Domus
// interactionsource.com
// Koji Pereira, Andre Veloso e Marcos Paulo

/*
 Projeto Domus
 interactionsource.com
 Koji Pereira, Andre Veloso e Marcos Paulo

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/


package com.interactionsource.output.midi;
import java.util.Vector;

import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.ShortMessage;


public class GerenciadorMIDI {

	
	private MidiDevice.Info[] listaDispositivosMIDI;
	
	private Vector<MidiDevice.Info> listaDispositivosMIDIOut;
	
	//Instancias dos dispositivos MIDI prontos para comunicacao
	private Vector<DispositivoMIDIOut> dispositivoMIDIOut;
	
	//Veor com os eventos MIDI out inicializados e disponibilizados para uso
	private Vector<EventoMIDIOut> eventosMIDIOut;
	
	public GerenciadorMIDI () {
		
		MidiDevice dispositivoMIDI;
		
		dispositivoMIDIOut = new Vector<DispositivoMIDIOut>();
		
		listaDispositivosMIDIOut = new Vector<MidiDevice.Info>();
		
		listaDispositivosMIDI = MidiSystem.getMidiDeviceInfo();
		
		eventosMIDIOut = new Vector<EventoMIDIOut>();		
		
		for (int i=0; i < listaDispositivosMIDI.length; i++) {
			
			
			try {
				dispositivoMIDI = MidiSystem.getMidiDevice(listaDispositivosMIDI[i]);
				
				//System.out.println( "Dispositivo MIDI " + i + " - " 
				//           + listaDispositivosMIDI[i].getName() +
				//           " Receptores: " + dispositivoMIDI.getMaxReceivers() );
				
				//Identifica os dispositivos MIDI que sao de saida
				if (dispositivoMIDI.getMaxReceivers() == -1) {
					listaDispositivosMIDIOut.addElement(listaDispositivosMIDI[i]);
					

				}
				
			} catch (MidiUnavailableException e) {

				//e.printStackTrace();
				System.out.println("GerenciadorMIDI - Dispositivo MIDI nao Disponivel");
			}


		}
		
		//Inicializa os dispositivos MIDI de saida
		for (int j=0; j<listaDispositivosMIDIOut.size(); j++) {	
			this.iniciaDispositivoMIDIOutByName(
		         listaDispositivosMIDIOut.elementAt(j).getName() );	
		}
	}
	
	protected void finalize() throws Throwable
	{
	  //Finaliza os dispositivos um a um
		for (int i=0; i< dispositivoMIDIOut.size(); i++) {
			// TODO Removido por causa de um erro na versao MacOSX
			//dispositivoMIDIOut.elementAt(i).close();
		}
	} 	
	
	
	public MidiDevice.Info[] getListaDispositivosMIDI() {
		return listaDispositivosMIDI;
	}

	
	public void setListaDispositivosMIDI(MidiDevice.Info[] listaDispositivosMIDI) {
		this.listaDispositivosMIDI = listaDispositivosMIDI;
	}	

	public String[] getNamesDispositivoMIDIOut() {
				
		String[] nomes = new String[listaDispositivosMIDIOut.size()];
		

		for (int i=0; i < listaDispositivosMIDIOut.size(); i++) {
			nomes[i] = listaDispositivosMIDIOut.elementAt(i).getName();
			
		}
		
		return nomes;
		
	}
	
	
	public MidiDevice.Info getInfoDispositivosMIDI(int id) {
		return listaDispositivosMIDI[id];
	}	
	
	
	public void enviaMsgAgora(int idDispMIDI, ShortMessage msg) {
		dispositivoMIDIOut.elementAt(idDispMIDI).enviaMsgAgora(msg);
		
	}	
	
	public DispositivoMIDIOut getDispositivoMIDIOutByName(String name) {
							
		for (int i=0; i < this.dispositivoMIDIOut.size(); i++) {
			
			if  (this.dispositivoMIDIOut.elementAt(i).getDispositivoMIDIName() == name) {
				System.out.println("GerenciadorMIDI - Retornou getDispositivoMIDIOutByName - " + 
						this.dispositivoMIDIOut.elementAt(i).getDispositivoMIDIName() );
				
				return 	dispositivoMIDIOut.elementAt(i);			
			}
			
		}		
		
		return null;		
		
	}
	
	private void iniciaDispositivoMIDIOutByName(String name) {
			
		MidiDevice dispositivoMIDI;
		
		int pos = 0;
		
		for (int i=0; i < this.listaDispositivosMIDI.length; i++) {
			
			if  (this.listaDispositivosMIDI[i].getName() == name) {
				pos = i;				
			}
		}
		
		try {
			dispositivoMIDI = MidiSystem.getMidiDevice(listaDispositivosMIDI[pos]);
			
			//System.out.println( "GerenciadorMIDI - Dispositivo MIDI " + pos + " - " 
			//          + listaDispositivosMIDI[pos].getName() +
			//           " Receptores: " + dispositivoMIDI.getMaxReceivers() );
			
			if (dispositivoMIDI.getMaxReceivers() == -1) {
				this.dispositivoMIDIOut.add(new DispositivoMIDIOut(dispositivoMIDI));
				
			}
			
		} catch (MidiUnavailableException e) {
			
			//e.printStackTrace();
			System.out.println("GerenciadorMIDI - Dispositivo MIDI nao Disponivel");
		}
				
	}
	
	/**
	 * @param nomeDispositivoMIDIOut
	 * @param tipo
	 * @param canal
	 * @param dado
	 * @return EventoMIDIOut, null caso o dispositivo nao seja encontrado
	 */
	public EventoMIDIOut getNewEventoMIDIOut(String nomeDispositivoMIDIOut, int tipo, int canal, int dado) {
		
		int pos = 100;
		
		for (int i=0; i < this.dispositivoMIDIOut.size(); i++) {
			
			if  (this.dispositivoMIDIOut.elementAt(i).getDispositivoMIDIName().equals(nomeDispositivoMIDIOut) ) {
				pos = i;				
			}
		}		
		
		if (pos == 100) {
			
			return null;
		}
		
		EventoMIDIOut eventosMIDIOut = new EventoMIDIOut(dispositivoMIDIOut.elementAt(pos), tipo, canal, dado);
		
		this.eventosMIDIOut.add(eventosMIDIOut);
		
		System.out.println( "GerenciadorMIDI - Novo EventoMIDIOut: "
				+ eventosMIDIOut.toString());
		
		return this.eventosMIDIOut.lastElement();			
		
	}
	
}
